package com.whlilong.jxc.print;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * This class is intended for subclassing.
 * 
 * It offers functionality for displaying a picture in the dialog's header and
 * for adding buttons (right- and left-adjusted) in the dialogs footer.
 * Additionally, it offers an easy tool bar creating mechanism.
 * 
 * The events generated by buttons and toolitems can be handled in the method
 * onButton and onToolItem.
 * 
 * If not changed by the customer, the main Layout guiMainLayout has a
 * gridLayout(). Overwrite createMainAreaLayout() to change that.
 * 
 * @author Friederich Kupzog
 */
public class KDialog {

  /**
   * 
   */
  protected Shell guiShell;

  protected Display guiDisplay;

  protected Composite guiPictureArea;

  protected Composite guiToolBarArea;

  protected Composite guiMainArea;

  protected Composite guiButtonArea;

  protected Button guiLastLeftBut, guiLastRightBut;

  protected Control guiLastToolControl;

  protected Layout guiMainAreaLayout;

  protected Label guiPictureLabel;

  protected ToolBar guiToolBar;

  protected GridData guiPictureGridData;

  protected GridData guiToolBarGridData;

  /**
   * Cretaes a new, top level dialog.
   */
  public KDialog() {
    createShell(null);
  }

  /**
   * Creates a new Dialog.
   * 
   * @param parent
   *            The parent shell for this dialog.
   */
  public KDialog(Shell parent) {
    createShell(parent);
  }

  /**
   * Creates a new Dialog.
   * 
   * @param parent
   *            The parent shell for this dialog.
   * @param title
   *            The Dialog's title
   */
  public KDialog(Shell parent, String title) {
    this(parent);
    setTitle(title);
  }

  /**
   * Creates a new Dialog.
   * 
   * @param parent
   *            The parent shell for this dialog.
   * @param title
   *            The Dialog's title
   * @param icon
   *            The dialog's window icon.
   */
  public KDialog(Shell parent, String title, Image icon) {
    this(parent);
    setTitle(title);
    setShellImage(icon);
  }

  /*
   * Baut das Shell-Objekt auf und die Composits der 1. Ebene
   */
  protected void createShell(Shell parent) {
    guiDisplay = Display.getCurrent();

    // Shell
    if (parent != null)
      guiShell = new Shell(parent, getShellStyle());
    else
      guiShell = new Shell(Display.getCurrent(), getShellStyle());

    createShellLayout();
    createShellComposits();

  }

  protected void createShellComposits() {

    // picture area
    guiPictureArea = new Composite(guiShell, SWT.NONE);
    guiPictureGridData = new GridData();
    guiPictureGridData.grabExcessHorizontalSpace = true;
    guiPictureGridData.horizontalAlignment = GridData.FILL;
    guiPictureGridData.heightHint = 0;
    guiPictureArea.setLayoutData(guiPictureGridData);

    // ToolBar area
    guiToolBarArea = new Composite(guiShell, SWT.NONE);
    guiToolBarGridData = new GridData();
    guiToolBarGridData.grabExcessHorizontalSpace = true;
    guiToolBarGridData.horizontalAlignment = GridData.FILL;
    guiToolBarGridData.heightHint = 0;
    guiToolBarArea.setLayoutData(guiToolBarGridData);

    // main area
    guiMainArea = new Composite(guiShell, SWT.NONE);
    createMainAreaLayout();
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.FILL;
    gd.grabExcessVerticalSpace = true;
    gd.verticalAlignment = GridData.FILL;
    guiMainArea.setLayoutData(gd);

    // button area
    createButtonBar();
  }

  protected void createButtonBar() {
    // AuBeres Composite
    guiButtonArea = new Composite(guiShell, SWT.NONE);
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.FILL;
    guiButtonArea.setLayoutData(gd);

    FormLayout butLayout = new FormLayout();
    guiButtonArea.setLayout(butLayout);

    // Trennlinie
    Label sep = new Label(guiButtonArea, SWT.SEPARATOR | SWT.HORIZONTAL);
    FormData fd = new FormData();
    fd.bottom = new FormAttachment(100, -32);
    fd.left = new FormAttachment(0, 0);
    fd.right = new FormAttachment(100, 0);
    sep.setLayoutData(fd);

  }

  protected void createMainAreaLayout() {
    guiMainAreaLayout = new GridLayout();
    ((GridLayout) guiMainAreaLayout).makeColumnsEqualWidth = false;
    ((GridLayout) guiMainAreaLayout).numColumns = 1;
    guiMainArea.setLayout(guiMainAreaLayout);
  }

  /**
   * Factorymethod for pre-configured GridData objects
   * 
   * Configurates: grabExcessHorizontalSpace = true horizontalAlignment =
   * GridData.BEGINNING
   * 
   * @return GridData
   */
  public static GridData createGridData() {
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.BEGINNING;
    return gd;
  }

  /**
   * Factorymethod for pre-configured GridData objects
   * 
   * Configurates: grabExcessHorizontalSpace = true horizontalAlignment =
   * GridData.BEGINNING heightHint = hint
   * 
   * @return GridData
   */

  public static GridData createGridDataHHint(int hint) {
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.heightHint = hint;
    gd.horizontalAlignment = GridData.BEGINNING;
    return gd;
  }

  /**
   * Factorymethod for pre-configured GridData objects
   * 
   * Configurates: grabExcessHorizontalSpace = true horizontalAlignment =
   * GridData.FILL horizontalSpan = columns verticalAlignment = GridData.FILL
   * 
   * @return GridData
   */
  public static GridData createGridDataFill(int columns) {
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.FILL;
    gd.verticalAlignment = GridData.FILL;
    gd.horizontalSpan = columns;
    return gd;
  }

  /**
   * Factorymethod for pre-configured GridData objects
   * 
   * Configurates: grabExcessHorizontalSpace = true horizontalAlignment =
   * GridData.FILL horizontalSpan = columns verticalAlignment = GridData.FILL
   * horizontalIndent = hIndent
   * 
   * @return GridData
   */
  public static GridData createGridDataFill(int columns, int hIndent) {
    GridData gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.FILL;
    gd.verticalAlignment = GridData.FILL;
    gd.horizontalSpan = columns;
    gd.horizontalIndent = hIndent;
    return gd;
  }

  protected void createShellLayout() {
    GridLayout layout = new GridLayout(1, true);
    guiShell.setLayout(layout);
    layout.horizontalSpacing = 0;
    layout.verticalSpacing = 0;
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    guiShell.setLayout(layout);
  }

  /**
   * Returns the style of the dialog. Is also used during shell creation.
   * Overwrite this method to give your dialog another style.
   * 
   * @return int
   */
  public int getShellStyle() {
    return SWT.CLOSE | SWT.RESIZE;
  }

  /**
   * This method should create the dialogs GUI and is NOT called by the
   * KDialog constructor. Overwrite this method to build add your own widgets
   * to the dialog. Do not forget to call it in your own constructor.
   */
  protected void createContents() {
    /*
     * new Text(guiMainArea,SWT.BORDER); addButton("Ha!",""); addButton("Du
     * langer Button",""); addButtonRight("Close","");
     * addButtonRight("Komfort","",true);
     */
  }

  /**
   * Overwrite this method, if you whish your dioalog having a specific size
   * (use guiShell.setSize())
   */
  protected void doLayout() {
    guiShell.pack();
  }

  /**
   * This method opens the dialogs and processes events until the shell is
   * closed. You do not need to overwrite this method. Use close() to close
   * the dialog programmatically.
   */
  public void open() {
    doLayout();
    doPositioning();
    guiShell.open();
    while (!guiShell.isDisposed()) {
      if (!guiDisplay.readAndDispatch())
        guiDisplay.sleep();
    }
    guiShell.dispose();
  }

  public void close() {
//    guiShell.close();
    guiShell.dispose();
  }

  /**
   * This method centers the dialog on the screen. Overwrite this method if
   * you whish another position.
   */
  protected void doPositioning() {
    guiShell
        .setLocation(
            (guiDisplay.getBounds().width - guiShell.getBounds().width) / 2,
            (guiDisplay.getBounds().height - guiShell.getBounds().height) / 2);
    System.out.println(String.valueOf((guiDisplay.getBounds().width - guiShell.getBounds().width) / 2));
    System.out.println(String.valueOf((guiDisplay.getBounds().height - guiShell.getBounds().height) / 2));
  }

  /**
   * Sets the icon of the shell.
   * 
   * @param image
   */
  public void setShellImage(Image image) {
    guiShell.setImage(image);
  }

  /**
   * Sets the window title.
   * 
   * @param title
   */
  public void setTitle(String title) {
    guiShell.setText(title);
  }

  /**
   * Sets the image displayed in the dialogs header.
   * 
   * @param image
   */
  public void setDialogImage(Image image) {
    guiPictureArea
        .setBackground(guiDisplay.getSystemColor(SWT.COLOR_WHITE));

    guiPictureGridData.heightHint = image.getBounds().height + 2;

    GridLayout layout = new GridLayout(1, true);
    guiPictureArea.setLayout(layout);
    layout.horizontalSpacing = 0;
    layout.verticalSpacing = 0;
    layout.marginHeight = 0;
    layout.marginWidth = 0;

    guiPictureLabel = new Label(guiPictureArea, SWT.NONE);
    guiPictureLabel.setImage(image);
    // guiPictureLabel.setBackground(guiDisplay.getSystemColor(SWT.COLOR_WHITE));
    GridData gd = new GridData();
    // gd.grabExcessHorizontalSpace = true;
    // gd.horizontalAlignment = GridData.FILL;
    guiPictureLabel.setLayoutData(gd);

    Label line = new Label(guiPictureArea, SWT.SEPARATOR | SWT.HORIZONTAL);
    gd = new GridData();
    gd.grabExcessHorizontalSpace = true;
    gd.horizontalAlignment = GridData.FILL;
    line.setLayoutData(gd);
  }

  /**
   * Adds a ToolItem to the dialog's toolbar. Creates the toolbar if not
   * already done.
   * 
   * @param name
   *            The name if the ToolItem. Although this name is never
   *            displayed to the user you can use it in onToolItem to identify
   *            the activated ToolItem.
   * @param tooltip
   *            The item's tooltip
   * @param icon
   *            The icon to show.
   * @return ToolItem The ToolItem created by this method.
   */
  public ToolItem addToolItem(String name, String tooltip, Image icon) {
    if (guiToolBar == null) {
      FormLayout layout = new FormLayout();
      guiToolBarArea.setLayout(layout);
      // layout.horizontalSpacing = 0;
      // layout.verticalSpacing = 0;
      layout.marginHeight = 0;
      layout.marginWidth = 0;

      guiToolBar = new ToolBar(guiToolBarArea, SWT.FLAT);
      FormData fd = new FormData();
      fd.left = new FormAttachment(0, 0);
      fd.top = new FormAttachment(0, 0);
      guiToolBar.setLayoutData(fd);

      Label line = new Label(guiToolBarArea, SWT.SEPARATOR
          | SWT.HORIZONTAL);
      fd = new FormData();
      fd.left = new FormAttachment(0, 0);
      fd.top = new FormAttachment(guiToolBar, 1);
      fd.right = new FormAttachment(100, 0);
      line.setLayoutData(fd);

      guiLastToolControl = guiToolBar;

    }
    ToolItem ti = new ToolItem(guiToolBar, SWT.PUSH);
    ti.setImage(icon);
    ti.setToolTipText(tooltip);
    ti.setEnabled(true);
    ti.setData(name);
    ti.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        onToolItem((ToolItem) e.widget, (String) e.widget.getData());
      }
    });

    guiToolBarGridData.heightHint = guiToolBarArea.computeSize(SWT.DEFAULT,
        SWT.DEFAULT).y;
    return ti;
  }

  public void adjustToToolBar(Control c) {
    FormData fd = new FormData();
    fd.left = new FormAttachment(guiLastToolControl, 2);
    fd.top = new FormAttachment(0, 0);
    fd.bottom = new FormAttachment(0, 24);

    c.setLayoutData(fd);
    guiLastToolControl = c;
  }

  protected Button addButton(boolean rightAdjusted, String text, String tip) {
    Button erg = new Button(guiButtonArea, SWT.PUSH);
    erg.setText(text);
    erg.setToolTipText(tip);

    Point butPrefferedSize = erg.computeSize(SWT.DEFAULT, SWT.DEFAULT);

    FormData fd = new FormData();
    fd.bottom = new FormAttachment(100, -3);

    if (butPrefferedSize.x > 70)
      fd.width = butPrefferedSize.x + 4;
    else
      fd.width = 70;
    fd.height = 24;
    erg.setLayoutData(fd);

    if (rightAdjusted) {
      if (guiLastRightBut == null)
        fd.right = new FormAttachment(100, -3);
      else
        fd.right = new FormAttachment(guiLastRightBut, -3);
      guiLastRightBut = erg;
    } else {
      if (guiLastLeftBut == null)
        fd.left = new FormAttachment(0, 3);
      else
        fd.left = new FormAttachment(guiLastLeftBut, 3);
      guiLastLeftBut = erg;
    }

    erg.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent arg0) {
        onButton((Button) arg0.widget, ((Button) arg0.widget).getText());
      }
    });
    return erg;
  }

  /**
   * Puts a Button into the button bar in the dialog's footer (right
   * adjusted). To handle the event produced by this button see onButton().
   * 
   * @param text
   * @param toolTip
   * @return Button The Button produced by this method.
   */
  public Button addButtonRight(String text, String toolTip) {
    return addButton(true, text, toolTip);
  }

  /**
   * Puts a Button into the button bar in the dialog's footer (left adjusted).
   * To handle the event produced by this button see onButton().
   * 
   * @param text
   * @param toolTip
   * @return Button The Button produced by this method.
   */
  public Button addButton(String text, String toolTip) {
    return addButton(false, text, toolTip);
  }

  /**
   * Puts a Button into the button bar in the dialog's footer (right
   * adjusted). To handle the event produced by this button see onButton().
   * 
   * @param text
   * @param toolTip
   * @param isDefault
   *            if true, this button will become the default button
   * @return Button The Button produced by this method.
   */
  public Button addButtonRight(String text, String toolTip, boolean isDefault) {
    Button erg = addButton(true, text, toolTip);
    if (isDefault)
      guiShell.setDefaultButton(erg);
    return erg;
  }

  /**
   * Puts a Button into the button bar in the dialog's footer (left adjusted).
   * To handle the event produced by this button see onButton().
   * 
   * @param text
   * @param toolTip
   * @param isDefault
   *            if true, this button will become the default button
   * @return Button The Button produced by this method.
   */
  public Button addButton(String text, String toolTip, boolean isDefault) {
    Button erg = addButton(false, text, toolTip);
    if (isDefault)
      guiShell.setDefaultButton(erg);
    return erg;
  }

  /*
   * Button-clicks call this method. Overwrite it to react on button clicks.
   */
  protected void onButton(Button button, String buttonText) {
  }

  /*
   * clicked ToolItems call this method. Overwrite it to react on button
   * clicks.
   */
  protected void onToolItem(ToolItem toolitem, String name) {
  }

}